#include "ConnectionPool.h"

/* 下面是数据库连接池处理部分 */
ConnectionPool::ConnectionPool(int numConnections,
                               string connectionName,
                               string database,
                               string username,
                               string password,
                               string host,
                               int port) :
        isDestroying_(false),
        numConnections_(numConnections),
        maxNumConnections_(std::min(numConnections * 2, 64)),
        name_(std::move(connectionName)),
        nextInd_(0),
        database_(std::move(database)),
        username_(std::move(username)),
        password_(std::move(password)),
        host_(std::move(host)),
        port_(port) {
    assert(numConnections_ > 0);
    for (int i = 0; i < numConnections_; ++i) {
        addConnection(i);
    }
    LOG_DEBUG << "数据库连接池 [" << name_ << "] 初始化完毕, 初始化连接数量 : " << numConnections_;
}

ConnectionPool::ConnectionPool(int numConnections,
                               const string &database,
                               const string &username,
                               const string &password,
                               const string &host,
                               int port) :
        ConnectionPool(numConnections,
                       "BasePoolConnection",
                       database,
                       username,
                       password,
                       host,
                       port) {}

ConnectionPool::~ConnectionPool() {
    LOG_DEBUG << "数据库连接池[" << name_ << "]开始销毁";
    destroyConnPool();
    LOG_DEBUG << "数据库连接池[" << name_ << "]销毁结束";
}


ConnectionPool::Connection ConnectionPool::getConnection() {
    // 正在销毁中, 直接返回空连接即可
    {
        MutexLockGuard lock(mutex_);
        if (isDestroying_) return nullptr;
        if (freeConnections_.empty()) {
            // 当前容量不足, 判断是否需要进行扩容操作
            if (numConnections_ == maxNumConnections_) {
                // 此时容量已满, 直接返回空的连接
                return nullptr;
            }
            int num = 1;
            if (numConnections_ < maxNumConnections_ * 3 / 4) {
                num = std::min(numConnections_ * 2, maxNumConnections_ * 3 / 4);
            }
            for (int i = 1; i <= num; ++i) {
                addConnection(i + numConnections_);
            }
            numConnections_ += num;
            LOG_DEBUG << "数据库连接池 [" << name_ << "] 扩容成功, 扩展连接数量 : " << num;
        }
        return getConnFromQue();
    }
}

// FIXME :
void ConnectionPool::closeConnection(ConnectionPool::Connection *conn) {
    {
        MutexLockGuard lock(mutex_);
        // 将连接从活动数据库连接从移除
        activeConnections_.erase((*conn));
        // 连接依旧有效, 将连接存回连接池
        if ((*conn) != nullptr) freeConnections_.push_back(*conn);
        (*conn) = nullptr;
        // 清空连接
    }
    LOG_DEBUG << "线程[" << CurrentThread::name() << "]归还了数据库连接, "
                                                   "当前数据库空闲连接数量 : "
              << freeConnections_.size()
              << ", 活动连接数量"
              << activeConnections_.size();
}

void ConnectionPool::destroyConnPool() {
    LOG_TRACE << "开始进行数据库连接池[" << name_ << "]的销毁工作";
    {
        MutexLockGuard lock(mutex_);
        isDestroying_ = true;
        for (Connection it : connections_) {
            delete it;
        }
        connections_.clear();
        freeConnections_.clear();
        activeConnections_.clear();
        isDestroying_ = false;
    }
    LOG_TRACE << "数据库连接池[" << name_ << "]成功销毁";
}


void ConnectionPool::addConnection(int index) {
    Connection conn = new MySQLConnection(name_ + std::to_string(index),
                                          database_,
                                          username_,
                                          password_,
                                          host_,
                                          port_);
    connections_.push_back(conn);
    freeConnections_.push_back(conn);
    // 将连接保存起来
}

ConnectionPool::Connection ConnectionPool::getConnFromQue() {
    Connection conn = freeConnections_.front();
    freeConnections_.pop_front();
    activeConnections_.insert(conn);
    LOG_DEBUG << "线程[" << CurrentThread::name() << "]获取了数据库连接, "
                                                   "当前数据库空闲连接数量 : "
              << freeConnections_.size()
              << ", 活动连接数量"
              << activeConnections_.size();
    return conn;
    // 将连接返回
}


// FIXME: 此处的连接二次封装暂时废弃
/*ConnectionPool::DataBaseConnection::DataBaseConnection() : isValid_(false), expire_(Timestamp::now()), connection_(nullptr), index_(-1){}

ConnectionPool::DataBaseConnection::DataBaseConnection(const Timestamp &expire, MySQLConnection * conn, int64_t index)  :
                                       isValid_(true),
                                       expire_(expire),
                                       connection_(conn),
                                       index_(index){}

ConnectionPool::DataBaseConnection::~DataBaseConnection() {
     // FIXME : 原因可能是这里的析构函数;
}

void ConnectionPool::DataBaseConnection::destroyConn() {
    isValid_ = false;
    connection_ = nullptr;
}

bool ConnectionPool::DataBaseConnection::expire() {
    if(isValid_ && connection_ != nullptr){
        if(Timestamp::now().microSecondsSinceEpoch() >= expire_.microSecondsSinceEpoch()) {
            // 惰性删除, 如果发现当前节点过期了就进行释放
            destroyConn();
        }else{
            return true;
        }
    }
    return false;
}

MySQLConnection::fieldsVector ConnectionPool::DataBaseConnection::select(const string &sql) {
        if(!expire()) return {};
        else return connection_->select(sql);
}

bool ConnectionPool::DataBaseConnection::query(const string &sql) {
    if(!expire()) return false;
    else return connection_->query(sql);
}*/
